/*
 * Copyright (C) 2010 Moduad Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cc.telecomdigital.tdstock.activity.groups.more.push.client;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

/**
 * Service that continues to run in background and respond to the push
 * notification events from the server. This should be registered as service in
 * AndroidManifest.xml.
 * 
 * @author Sehwan Noh (devnoh@gmail.com)
 */
public class NotificationService extends Service
{
	private static final String	TAG			= NotificationService.class
												.getSimpleName();

	public static final String	SERVICE_NAME	= "cc.telecomdigital.tdstock.activity.groups.more.push.client.NotificationService";

	private TelephonyManager		telephonyManager;

	// private WifiManager wifiManager;
	//
	// private ConnectivityManager connectivityManager;

	private BroadcastReceiver	notificationReceiver;

	private BroadcastReceiver	connectivityReceiver;

	private PhoneStateListener	phoneStateListener;

	private ExecutorService		executorService;

	private TaskSubmitter		taskSubmitter;

	private TaskTracker			taskTracker;

	private XmppManager			xmppManager;

	private SharedPreferences	sharedPrefs;

	private String				deviceId;

	public static boolean		flag			= false;

	/*
	 * private TestConnection.Stub stub=new TestConnection.Stub() {
	 * 
	 * @Override public boolean getConnection() throws RemoteException { // TODO
	 * Auto-generated method stub return
	 * NotificationService.this.getXmppManager().getConnection().isConnected();
	 * } };
	 */

	public NotificationService()
	{
		notificationReceiver = new NotificationReceiver();
		connectivityReceiver = new ConnectivityReceiver(this);
		phoneStateListener = new PhoneStateChangeListener(this);
		executorService = Executors.newSingleThreadExecutor();
		taskSubmitter = new TaskSubmitter(this);
		taskTracker = new TaskTracker(this);
		//setForeground(true);
		TDStockLog.d(TAG, "NotificationService  start .......");
	}

	@Override
	public void onCreate()
	{
		TDStockLog.d(TAG, "onCreate()...");
		startService(TAG);
	}

	@Override
	public void onStart(Intent intent, int startId)
	{
		TDStockLog.d(TAG, "onStart()...");
		if (flag)
		{
			TDStockLog.d(TAG, "onReStart()...");
			startService(TAG);
			flag = false;
		}
	}

	@Override
	public void onDestroy()
	{
		TDStockLog.d(TAG, "onDestroy()...");
		stop();
		//Notifier.clearAllNotification();
	}

	@Override
	public IBinder onBind(Intent intent)
	{
		TDStockLog.d(TAG, "onBind()...");
		return null;
	}

	@Override
	public void onRebind(Intent intent)
	{
		TDStockLog.d(TAG, "onRebind()...");
	}

	@Override
	public boolean onUnbind(Intent intent)
	{
		TDStockLog.d(TAG, "onUnbind()...");
		return true;
	}

	public static Intent getIntent()
	{
		return new Intent(SERVICE_NAME);
	}

	public ExecutorService getExecutorService()
	{
		return executorService;
	}

	public TaskSubmitter getTaskSubmitter()
	{
		return taskSubmitter;
	}

	public TaskTracker getTaskTracker()
	{
		return taskTracker;
	}

	public XmppManager getXmppManager()
	{
		return xmppManager;
	}

	public SharedPreferences getSharedPreferences()
	{
		return sharedPrefs;
	}

	public String getDeviceId()
	{
		return deviceId;
	}

	public void connect(String form)
	{
		TDStockLog.d(TAG, String.format("connect()...,From to %s",
				form == null ? TAG : form));
		taskSubmitter.submit(new Runnable()
		{
			public void run()
			{
				XmppManager.waiting = 0;
				NotificationService.this.getXmppManager()
						.startReconnectionThread(TAG);
			}
		});
	}

	public void disconnect()
	{
		TDStockLog.d(TAG, "disconnect()...");
		taskSubmitter.submit(new Runnable()
		{
			public void run()
			{
				NotificationService.this.getXmppManager().disconnect();
			}
		});
	}

	private void registerNotificationReceiver()
	{
		IntentFilter filter = new IntentFilter();
		filter.addAction(Constants.ACTION_SHOW_NOTIFICATION);
		filter.addAction(Constants.ACTION_NOTIFICATION_CLICKED);
		filter.addAction(Constants.ACTION_NOTIFICATION_CLEARED);
		registerReceiver(notificationReceiver, filter);
	}

	private void unregisterNotificationReceiver()
	{
		unregisterReceiver(notificationReceiver);
	}

	private void registerConnectivityReceiver()
	{
		TDStockLog.d(TAG, "registerConnectivityReceiver()...");
		telephonyManager.listen(phoneStateListener,
				PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
		telephonyManager.listen(phoneStateListener,
				PhoneStateListener.LISTEN_SIGNAL_STRENGTH);
		IntentFilter filter = new IntentFilter();
		// filter.addAction(android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION);
		filter.addAction(android.net.ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(connectivityReceiver, filter);
	}

	private void unregisterConnectivityReceiver()
	{
		TDStockLog.d(TAG, "unregisterConnectivityReceiver()...");
		telephonyManager.listen(phoneStateListener,
				PhoneStateListener.LISTEN_NONE);
		unregisterReceiver(connectivityReceiver);
	}

	private void start()
	{
		TDStockLog.d(TAG, "start()...");
		registerNotificationReceiver();
		registerConnectivityReceiver();
		// Intent intent = getIntent();
		// startService(intent);
		xmppManager.connect();
	}

	public void stop()
	{
		TDStockLog.d(TAG, "stop()...");
		unregisterNotificationReceiver();
		unregisterConnectivityReceiver();
		xmppManager.disconnect();
		executorService.shutdown();
	}

	/**
	 * start service
	 */
	public void startService(String form)
	{
		TDStockLog.d(TAG, "from to " + (form == null ? "" : form));
		telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		// wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		// connectivityManager = (ConnectivityManager)
		// getSystemService(Context.CONNECTIVITY_SERVICE);

		sharedPrefs = getSharedPreferences(Constants.SHARED_PREFERENCE_NAME,
				Context.MODE_PRIVATE);

		// Get deviceId
		deviceId = telephonyManager.getDeviceId();
		// Log.d(LOGTAG, "deviceId=" + deviceId);
		Editor editor = sharedPrefs.edit();
		editor.putString(Constants.DEVICE_ID, deviceId);
		editor.commit();

		// If running on an emulator
		if (deviceId == null || deviceId.trim().length() == 0
				|| deviceId.matches("0+"))
		{
			if (sharedPrefs.contains("EMULATOR_DEVICE_ID"))
			{
				deviceId = sharedPrefs.getString(
						Constants.EMULATOR_DEVICE_ID, "");
			}
			else
			{
				deviceId = (new StringBuilder("EMU")).append(
						(new Random(System.currentTimeMillis()))
								.nextLong()).toString();
				editor.putString(Constants.EMULATOR_DEVICE_ID, deviceId);
				editor.commit();
			}
		}
		TDStockLog.d(TAG, "deviceId=" + deviceId);

		xmppManager = new XmppManager(this);

		taskSubmitter.submit(new Runnable()
		{
			public void run()
			{

				NotificationService.this.start();
			}
		});
	}

	/**
	 * Class for summiting a new runnable task.
	 */
	public class TaskSubmitter
	{

		final NotificationService	notificationService;

		public TaskSubmitter(NotificationService notificationService)
		{
			this.notificationService = notificationService;
		}

		@SuppressWarnings("rawtypes")
		public Future submit(Runnable task)
		{
			Future result = null;
			if (!notificationService.getExecutorService().isTerminated()
					&& !notificationService.getExecutorService()
							.isShutdown() && task != null)
			{
				result = notificationService.getExecutorService().submit(
						task);
			}
			return result;
		}

	}

	/**
	 * Class for monitoring the running task count.
	 */
	public class TaskTracker
	{

		final NotificationService	notificationService;

		public int				count;

		public TaskTracker(NotificationService notificationService)
		{
			this.notificationService = notificationService;
			this.count = 0;
		}

		public void increase()
		{
			synchronized (notificationService.getTaskTracker())
			{
				notificationService.getTaskTracker().count++;
				TDStockLog.d(TAG, "Incremented task count to " + count);
			}
		}

		public void decrease()
		{
			synchronized (notificationService.getTaskTracker())
			{
				notificationService.getTaskTracker().count--;
				TDStockLog.d(TAG, "Decremented task count to " + count);
			}
		}

	}

}
